package com.nt.train.advice;

import com.nt.train.exception.APIException;
import com.nt.train.vo.JsonResult;
import com.nt.train.vo.ResponseInfo;
import com.nt.train.vo.Result;
import com.nt.train.vo.ResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.xml.bind.ValidationException;
import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * https://www.pudn.com/news/62e9c8df55398e076b19417e.html
 * @author hlf
 * @version 1.0
 * @date 2022/9/19 10:35
 */
@Slf4j
@RestControllerAdvice
public class ExceptionHandlerAdvice {

    /**
     * 参数格式异常处理
     */
    @ExceptionHandler({IllegalArgumentException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseInfo<String> badRequestException(IllegalArgumentException ex) {
        log.error("参数格式不合法：{}", ex.getMessage());
        return new ResponseInfo<>(HttpStatus.BAD_REQUEST.value() + "", "参数格式不符！");
    }

    /**
     * 权限不足异常处理
     */
    @ExceptionHandler({AccessDeniedException.class})
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public ResponseInfo<String> badRequestException(AccessDeniedException ex) {
        return new ResponseInfo<>(HttpStatus.FORBIDDEN.value() + "", ex.getMessage());
    }

    /**
     * 参数缺失异常处理
     */
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseInfo<String> badRequestException(Exception ex) {
        return new ResponseInfo<>(HttpStatus.BAD_REQUEST.value() + "", "缺少必填参数！");
    }

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseInfo<String> handleTypeMismatchException(NullPointerException ex) {
        log.error("空指针异常，{}", ex.getMessage());
        return ResponseInfo.fail("空指针异常");
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseInfo<String> handleUnexpectedServer(Exception ex) {
        log.error("系统异常：", ex);
        return ResponseInfo.fail("系统发生异常，请联系管理员");
    }

    /**
     * 系统异常处理
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseInfo<String> exception(Throwable throwable) {
        log.error("系统异常", throwable);
        return new ResponseInfo<>(HttpStatus.INTERNAL_SERVER_ERROR.value() + "系统异常，请联系管理员！");
    }

    @ExceptionHandler(APIException.class)
    public ResponseInfo<String> APIExceptionHandler(APIException e) {
        // 注意哦，这里返回类型是自定义响应体
        return new ResponseInfo<>(e.getCode(), "响应失败"+e.getMsg());
    }

    /** validation 校验参数 异常处理  */
//    @ExceptionHandler(value = BindException.class)
//    public JsonResult exceptionHandle(BindException exception) {
//        BindingResult result = exception.getBindingResult();
//        StringBuilder errorMsg = new StringBuilder();
//        List<FieldError> fieldErrors = result.getFieldErrors();
//        fieldErrors.forEach(error -> {
//            log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage());
//            errorMsg.append(error.getDefaultMessage()).append("!");
//        });
//        return JsonResult.fail(errorMsg.toString());
//    }
//
//    @ExceptionHandler(value = MethodArgumentNotValidException.class)
//    public JsonResult MyExceptionHandle(MethodArgumentNotValidException exception) {
//        BindingResult result = exception.getBindingResult();
//        StringBuilder errorMsg = new StringBuilder();
//
//        List<FieldError> fieldErrors = result.getFieldErrors();
//        fieldErrors.forEach(error -> {
//            log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage());
//            errorMsg.append(error.getDefaultMessage()).append("!");
//        });
//
//        return JsonResult.fail(errorMsg.toString());
//    }
//
//    // 处理运行时异常
//    @ExceptionHandler(RuntimeException.class)
//    public JsonResult doHandleRuntimeException(RuntimeException e) {
//        log.error(e.getMessage(), e);
//        e.printStackTrace();
//        return JsonResult.fail(e.getMessage());
//    }

//    /**
//     * https://blog.csdn.net/qq_30925199/article/details/125263431
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class,ConstraintViolationException.class})
//    public ResponseInfo handleValidatedException(Exception e) {
//        StringBuilder errorMsg = new StringBuilder();
//        if (e instanceof MethodArgumentNotValidException) {
//            // BeanValidation exception
//            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
//            errorMsg.append(ex.getBindingResult().getAllErrors().stream()
//                    .map(ObjectError::getDefaultMessage)
//                    .collect(Collectors.joining("; ")));
//        } else if (e instanceof ConstraintViolationException) {
//            // BeanValidation GET simple param
//            ConstraintViolationException ex = (ConstraintViolationException) e;
//            Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
//            errorMsg.append(violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")));
//        } else if (e instanceof BindException) {
//            BindException ex = (BindException) e;
//            errorMsg.append(ex.getAllErrors().stream().map(ObjectError::getDefaultMessage)
//                    .collect(Collectors.joining("; ")));
//        } else if (e instanceof ValidationException) {
//            ConstraintViolationException exs = (ConstraintViolationException) e;
//            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
//            errorMsg.append(violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")));
//        }
//
//         return  ResponseInfo.fail(errorMsg.toString());
//    }



}